/*!
 * \file tcompact.c
 *
 * \brief thrift tcompact 数据编码格式解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author geyh
 * \date 2017/02/15
 *
 */
#include "frcomm.h"
#include <module.h>
#include <frct_comm.h>
#include "frmem.h"
#include "tcompact.h"

#define VERSION_MASK            0x1f
#define TYPE_MASK               0xe0
#define TYPE_BITS               0X07
#define TYPE_SHIFT_AMOUNT       5

#define TM_CALL                 1
#define TM_REPLY                2
#define TM_EXCEPTION            3
#define TM_ONEWAY               4

#define BOOLEAN_TRUE            0x01
#define BOOLEAN_FALSE           0x02
#define BYTE                    0x03
#define I16                     0x04
#define I32                     0x05
#define I64                     0x06
#define DOUBLE                  0x07
#define BINARY                  0x08
#define LIST                    0x09
#define SET                     0x0a
#define MAP                     0x0b
#define STRUCT                  0x0c

#define TTYPE_STOP              0
#define TTYPE_VOID              1
#define TTYPE_BOOL              2
#define TTYPE_BYTE              3
#define TTYPE_DOUBLE            4
#define TTYPE_I16               6
#define TTYPE_I32               8


#define PROTOCOL_ID             0x82

union int64_double_bits {
    int64_t int_bits;
    double double_bits;
};


/* 4位小头节序转到本地字节序 */
#define pntohi(p)  ((unsigned int)*((const unsigned char *)(p + 0)) << 24 | \
                    (unsigned int)*((const unsigned char *)(p + 1)) << 16 | \
                    (unsigned int)*((const unsigned char *)(p + 2)) << 8 | \
                    (unsigned int)*((const unsigned char *)(p + 3)) << 0)

/*!
 * \brief       thrift tcompact 协议格式判断
 *
 * \arg         p_tcp_body   输入数据
 *              ui_tcp_body_len     数据长度
 *
 * \return      APM_L7_IS_NO
 *              APM_L7_IS_YES
 *
 */
int frthrift_tcompact_detect(unsigned char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    unsigned int ui_mes_len = 0;
    
    if(p_tcp_body == NULL || ui_tcp_body_len <= 6)
        return APM_L7_IS_NO;
    
    ui_mes_len = pntohi(p_tcp_body);
    ui_tcp_body_len -= 4;
    p_tcp_body += 4;
    
    if(ui_mes_len != ui_tcp_body_len)
        return APM_L7_IS_NO;
    
    //PROTOCOL_ID = 0x82
    if(p_tcp_body[0] != 0x82)
        return APM_L7_IS_NO;

    //PROTOCOL_ID = 0x82
    if((p_tcp_body[1] >> 5) > 4 || (p_tcp_body[1] >> 5) == 0)
        return APM_L7_IS_NO;
    
    return APM_L7_IS_YES;
    
}

/*!
 * \brief   判断thrift 数据方向
 *
 * \arg         p_tcp_body   输入数据
 *              ui_tcp_body_len     数据长度
 *
 * \return      FR_DIRECT_UNKNOWN
 *              FR_DIRECT_SRV2CLIENT
 *              FR_DIRECT_CLIENT2SRV
 *
 */
int frthrift_tcompact_direction_detect(unsigned char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    unsigned char uc_type = 0;
    unsigned char uc_versionAndType = 0;
    
    if(p_tcp_body == NULL || ui_tcp_body_len <= 6)
        return FR_DIRECT_UNKNOWN;
    
    uc_versionAndType = p_tcp_body[5];
    uc_type = (uc_versionAndType >> TYPE_SHIFT_AMOUNT & (unsigned char)TYPE_BITS);
    
    if(uc_type == TM_CALL)
        return FR_DIRECT_CLIENT2SRV;
    else if(uc_type == TM_REPLY || uc_type == TM_EXCEPTION)
        return FR_DIRECT_SRV2CLIENT;
    
    return FR_DIRECT_UNKNOWN;
}

/*!
 * \brief   读一个varint32
 *
 * \arg     p_packet    输入数据
 *          p_i_ret     出力参数
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int __read_varint32(Frbyte_Packet *p_packet, int *p_i_ret)
{
    int result = 0;
    int shift = 0;
    uint8_t u8_tmp = 0;

    if(p_packet == NULL)
        return FR_FAIL;
    
    while (1)
    {
        if(bytebuff_get_char(p_packet, &u8_tmp) == FR_FAIL)
            return FR_FAIL;

        result |= (u8_tmp & 0x7f) << shift;
        
        if ((u8_tmp & 0x80) != 0x80)
            break;

        shift += 7;

        if(shift > 32)
            return FR_FAIL;

    }
    
    *p_i_ret = result;
    
    return FR_SUCC;
    
}

/*!
 * \brief   读一个varint64
 *
 * \arg     p_packet    输入数据
 *          p_l_ret     出力参数
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int __read_varint64(Frbyte_Packet *p_packet, long *p_l_ret)
{
    long result = 0;
    int shift = 0;
    uint8_t u8_tmp = 0;
    
    if(p_packet == NULL)
        return FR_FAIL;
    
    while (1)
    {
        if(bytebuff_get_char(p_packet, &u8_tmp) == FR_FAIL)
            return FR_FAIL;
        
        result |= (long)(u8_tmp & 0x7f) << shift;
        
        if ((u8_tmp & 0x80) != 0x80)
            break;
        
        shift += 7;

        if(shift > 64)
            return FR_FAIL;

    }
    
    *p_l_ret = result;
    
    return FR_SUCC;
    
}

//
// encoding helpers
//
//FR_STATIC int isBoolType(uint8_t u8_type)
//{
//    int lowerNibble = u8_type & 0x0f;
//    return lowerNibble == BOOLEAN_TRUE || lowerNibble == BOOLEAN_FALSE;
//}

/*!
 * \brief   Convert from zigzag int to int.
 *
 * \arg     n        zigzag int
 *
 * \return  int
 *
 */
FR_STATIC int zigzagToInt(int n)
{
    return ((int)((unsigned int)n >> 1)) ^ -(n & 1);
}



/*!
 * \brief   Convert from zigzag long to long.
 *
 * \arg     n        zigzag long
 *
 * \return  long
 *
 */
FR_STATIC long zigzagToLong(long n)
{
    return ((long)((unsigned long)n >> 1)) ^ -(n & 1);
}


/*!
 * \brief   读一个byte
 *
 * \arg     p_packet        输入数据
 *          p_u8_ret        返回的byte
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readByte(Frbyte_Packet *p_packet, uint8_t *p_u8_ret)
{

    if(bytebuff_get_char(p_packet, p_u8_ret) == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * \brief   读一个 short
 *
 * \arg     p_packet        输入数据
 *          p_s_ret         返回的  short
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readI16(Frbyte_Packet *p_packet, short *p_s_ret)
{
    int i_tmp = 0;
    
    if(__read_varint32(p_packet, &i_tmp) == FR_FAIL)
        return FR_FAIL;
    
    *p_s_ret = (short)zigzagToInt(i_tmp);
    
    return FR_SUCC;
    
}

/*!
 * \brief   读一个 int
 *
 * \arg     p_packet        输入数据
 *          p_i_ret         返回的  int
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readI32(Frbyte_Packet *p_packet, int *p_i_ret)
{
    int i_tmp = 0;
    
    if(__read_varint32(p_packet, &i_tmp) == FR_FAIL)
        return FR_FAIL;
    
    *p_i_ret = zigzagToInt(i_tmp);
    
    return FR_SUCC;
    
}


/*!
 * \brief   读一个 long
 *
 * \arg     p_packet        输入数据
 *          p_l_ret         返回的  long
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readI64(Frbyte_Packet *p_packet, long *p_l_ret)
{
    long l_tmp = 0;
    
    if(__read_varint64(p_packet, &l_tmp) == FR_FAIL)
        return FR_FAIL;
    
    *p_l_ret = zigzagToLong(l_tmp);
    
    return FR_SUCC;
    
}


/*!
 * \brief   读一个 double
 *
 * \arg     p_packet        输入数据
 *          p_db_ret        返回的  double
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readDouble(Frbyte_Packet *p_packet, double *p_db_ret)
{
    long l_tmp = 0;
    union int64_double_bits u_64bits;
    
    if(bytebuff_get_long(p_packet, 8, (uint64_t *)&l_tmp, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    u_64bits.int_bits = l_tmp;
    *p_db_ret = u_64bits.double_bits;
    
    return FR_SUCC;
    
}

/*!
 * \brief   读一个 string
 *
 * \arg     p_packet        输入数据
 *          pp_ret          返回的  string
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readString(Frbyte_Packet *p_packet, char **pp_ret)
{
    int length = 0;
    char *p_str = NULL;
    
    if(__read_varint32(p_packet, &length) == FR_FAIL)
        return FR_FAIL;
    
    if(length > bytebuff_remaining(p_packet))
        return FR_FAIL;
    
    p_str = (char *)frmalloc((size_t)length + 1);
    if(p_str == NULL)
        return FR_FAIL;
    
    if(bytebuff_get_bytes(p_packet, p_str, (size_t )length) == FR_FAIL)
    {
        frfree(p_str);
        return FR_FAIL;
    }
    
    p_str[length] = '\0';
    *pp_ret = p_str;
    
    return FR_SUCC;
    
}

/*!
 * \brief   读一个 binary
 *
 * \arg     p_packet        输入数据
 *          pp_st_str       返回的  binary
 *
 * \return  FR_SUCC 成功
 *          FR_FAIL 失败
 *
 */
FR_STATIC int readBinary(Frbyte_Packet *p_packet, Frstr **pp_st_str)
{
    Frstr *p_st_str = NULL;
    int length = 0;
    char *p_str = NULL;
    
    if(__read_varint32(p_packet, &length) == FR_FAIL)
        return FR_FAIL;
    
    if(length > bytebuff_remaining(p_packet))
        return FR_FAIL;
    
    p_str = (char *)frmalloc((size_t)length);
    if(p_str == NULL)
        return FR_FAIL;
    
    if(bytebuff_get_bytes(p_packet, p_str, (size_t )length) == FR_FAIL)
    {
        frfree(p_str);
        return FR_FAIL;
    }
    
    p_st_str = frstr_new((size_t)length);
    frstr_append(p_st_str, p_str, (size_t)length);
    frfree(p_str);
    
    *pp_st_str = p_st_str;
    
    return FR_SUCC;
    
}



/*!
 * \brief       thrift tcompact 消息开始部分解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_message_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact, int i_use_request, char *p_prefix)
{
    uint8_t u8_proto_id = 0;
    uint8_t u8_versionAndType = 0;
    char *p_func = NULL;
    char arr_key[128];
    char *p_err_msg = NULL;
    
    if (p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_prefix == NULL)
        return FR_FAIL;
    
    if (bytebuff_get_char(p_packet, &u8_proto_id) == FR_FAIL)
        return FR_FAIL;
    
    if (u8_proto_id != PROTOCOL_ID)
        return FR_FAIL;
    
    if (bytebuff_get_char(p_packet, &u8_versionAndType) == FR_FAIL)
        return FR_FAIL;
    
    p_st_compact->u8_version = u8_versionAndType & (uint8_t) VERSION_MASK;
    p_st_compact->u8_type = (u8_versionAndType >> TYPE_SHIFT_AMOUNT) & (uint8_t) TYPE_BITS;
    
    if(__read_varint32(p_packet, &p_st_compact->i_sqlid) == FR_FAIL)
        return FR_FAIL;
    
    if(p_st_compact->u8_type == TM_EXCEPTION)
    {
        //todo
        frreport_body_l7_add_long(p_st_body_data, APM_REPORT_KEY_RESP_CODE, 1);

        //上报错误信息
        if (readString(p_packet, &p_err_msg) == FR_FAIL)
            return FR_FAIL;

        frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_RESP_ERR_MSG, p_err_msg);
        frfree(p_err_msg);

        return FR_SUCC;
    }
    
    //上报函数
    if (readString(p_packet, &p_func) == FR_FAIL)
        return FR_FAIL;
    
    if (i_use_request)
    {
        frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_func);
        
        snprintf(arr_key, sizeof(arr_key), "%s.func", p_prefix);
        frreport_body_l7_add_str(p_st_body_data, arr_key, p_func);
        frfree(p_func);
    }
    else
    {
        frfree(p_func);
    }
    
    return FR_SUCC;
    
}



/*!
 * \brief       thrift tcompact 内容开始部分解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_field_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_prefix)
{
    uint8_t u8_type = 0;
    short fieldId;
    char arr_key[128];
    int i_index = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_prefix == NULL)
        return FR_FAIL;
    
    while (1)
    {
        if(bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
            return FR_FAIL;
        
        if(u8_type == TTYPE_STOP)
            break;
        
        if(i_use_request)
        {
            i_index++;
            snprintf(arr_key, sizeof(arr_key), "%s.arg.%d", p_prefix, i_index);
        }
        else
        {
            snprintf(arr_key, sizeof(arr_key), "%s.return", p_prefix);
        }
        
        // mask off the 4 MSB of the type header. it could contain a field id delta.
        short modifier = (short)((u8_type & 0xf0) >> 4);
        
        if (modifier == 0) {
            // not a delta. look ahead for the zigzag varint field id.
            readI16(p_packet, &fieldId);
            
        } else {
            // has a delta. add the delta to the last read field id.
//        fieldId = (short)(lastFieldId_ + modifier);
        }
        
        switch (u8_type & 0x0f)
        {
            case BOOLEAN_TRUE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "true");
                break;
            
            case BOOLEAN_FALSE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "false");
                break;
            
            case BYTE:
                frthrift_tcompact_read_byte_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case I16:
                frthrift_tcompact_read_i16_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case I32:
                frthrift_tcompact_read_i32_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case I64:
                frthrift_tcompact_read_i64_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case DOUBLE:
                frthrift_tcompact_read_double_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case BINARY:
                frthrift_tcompact_read_binary_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case LIST:
                frthrift_tcompact_read_list_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case SET:
                frthrift_tcompact_read_set_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case MAP:
                frthrift_tcompact_read_map_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case STRUCT:
                frthrift_tcompact_read_struct_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            default:
                return FR_FAIL;
        }
        
    }
    
    if(i_use_request && i_index)
    {
        snprintf(arr_key, sizeof(arr_key), "%s.arg.size", p_prefix);
        frreport_body_l7_add_int(p_st_body_data, arr_key, i_index);
    }
    
    return FR_SUCC;
    
}

/*!
 * \brief       thrift tcompact struct 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_struct_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    uint8_t u8_type = 0;
    short fieldId;
    char arr_key[128];
    int i_index = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    while (1)
    {
        if(bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
            return FR_FAIL;
        
        if(u8_type == TTYPE_STOP)
            break;
        
        i_index++;
        snprintf(arr_key, sizeof(arr_key), "%s.struct.%d", p_name, i_index);
        
        // mask off the 4 MSB of the type header. it could contain a field id delta.
        short modifier = (short)((u8_type & 0xf0) >> 4);
        
        if (modifier == 0) {
            // not a delta. look ahead for the zigzag varint field id.
            readI16(p_packet, &fieldId);
//            p_st_compact->s_fieldid = fieldId;
        } else {
            // has a delta. add the delta to the last read field id.
//        fieldId = (short)(lastFieldId_ + modifier);
            fieldId = p_st_compact->s_fieldid + modifier;
        }
        
        switch (u8_type & 0x0f)
        {
            case BOOLEAN_TRUE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "true");
                break;
            
            case BOOLEAN_FALSE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "false");
                break;
            
            case BYTE:
                frthrift_tcompact_read_byte_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case I16:
                frthrift_tcompact_read_i16_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case I32:
                frthrift_tcompact_read_i32_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case I64:
                frthrift_tcompact_read_i64_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case DOUBLE:
                frthrift_tcompact_read_double_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case BINARY:
                frthrift_tcompact_read_binary_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case LIST:
                frthrift_tcompact_read_list_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case SET:
                frthrift_tcompact_read_set_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case MAP:
                frthrift_tcompact_read_map_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            case STRUCT:
                frthrift_tcompact_read_struct_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
            
            default:
                return FR_FAIL;
        }
        
    }
    
    if(i_index)
    {
        snprintf(arr_key, sizeof(arr_key), "%s.size", p_name);
        frreport_body_l7_add_int(p_st_body_data, arr_key, i_index);
    }
    else
    {
        frreport_body_l7_add_str(p_st_body_data, p_name, "NULL");
    }
    
    return FR_SUCC;
    
}

/*!
 * \brief       thrift tcompact map 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_map_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    int i_size = 0;
    uint8_t keyAndValueType = 0;
    uint8_t keyType = 0;
    uint8_t valueType = 0;
    char arr_key[128];
    int i_index = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(__read_varint32(p_packet, &i_size) == FR_FAIL)
        return FR_FAIL;
    
    if(i_size == 0)
    {
        snprintf(arr_key, sizeof(arr_key), "%s.map.key", p_name);
        frreport_body_l7_add_str(p_st_body_data, arr_key, "NULL");
        return FR_SUCC;
    }
    
    snprintf(arr_key, sizeof(arr_key), "%s.size", p_name);
    frreport_body_l7_add_int(p_st_body_data, arr_key, i_size);
    
    if(bytebuff_get_char(p_packet, &keyAndValueType) == FR_FAIL)
        return FR_FAIL;
    
    keyType = keyAndValueType >> 4 & (uint8_t)0x0f;
    valueType = keyAndValueType & (uint8_t)0x0f;
    
    while(i_size)
    {
        i_size--;
        i_index++;
        
        snprintf(arr_key, sizeof(arr_key), "%s.map.%d.key", p_name, i_index);
        
        switch (keyType)
        {
            case BOOLEAN_TRUE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "true");
                break;
    
            case BOOLEAN_FALSE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "false");
                break;
    
            case BYTE:
                frthrift_tcompact_read_byte_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case I16:
                frthrift_tcompact_read_i16_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case I32:
                frthrift_tcompact_read_i32_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case I64:
                frthrift_tcompact_read_i64_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case DOUBLE:
                frthrift_tcompact_read_double_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case BINARY:
                frthrift_tcompact_read_binary_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case LIST:
                frthrift_tcompact_read_list_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case SET:
                frthrift_tcompact_read_set_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case MAP:
                frthrift_tcompact_read_map_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case STRUCT:
                frthrift_tcompact_read_struct_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            default:
                return FR_FAIL;
            
        }
    
        snprintf(arr_key, sizeof(arr_key), "%s.map.%d.value", p_name, i_index);
    
        switch (valueType)
        {
            case BOOLEAN_TRUE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "true");
                break;
        
            case BOOLEAN_FALSE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "false");
                break;
        
            case BYTE:
                frthrift_tcompact_read_byte_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case I16:
                frthrift_tcompact_read_i16_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case I32:
                frthrift_tcompact_read_i32_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case I64:
                frthrift_tcompact_read_i64_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case DOUBLE:
                frthrift_tcompact_read_double_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case BINARY:
                frthrift_tcompact_read_binary_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case LIST:
                frthrift_tcompact_read_list_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case SET:
                frthrift_tcompact_read_set_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case MAP:
                frthrift_tcompact_read_map_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            case STRUCT:
                frthrift_tcompact_read_struct_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
        
            default:
                return FR_FAIL;
        
        }
        
    }
    
    return FR_SUCC;
    
}


/*!
 * \brief       thrift tcompact list 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_list_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    int i_size = 0;
    uint8_t size_and_type = 0;
    uint8_t u8_type = 0;
    char arr_key[128];
    int i_index = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(bytebuff_get_char(p_packet, &size_and_type) == FR_FAIL)
        return FR_FAIL;
    
    i_size = (size_and_type >> 4) & 0x0f;
    
    if(i_size == 15)
    {
        if(__read_varint32(p_packet, &i_size) == FR_FAIL)
            return FR_FAIL;
    }
    else if(i_size == 0)
    {
        snprintf(arr_key, sizeof(arr_key), "%s.list", p_name);
        frreport_body_l7_add_str(p_st_body_data, arr_key, "NULL");
        return FR_SUCC;
    }
    
    u8_type = size_and_type & (uint8_t)0x0f;
    
    
    while(i_size)
    {
        i_size--;
        i_index++;
        snprintf(arr_key, sizeof(arr_key), "%s.list.%d", p_name, i_index);
        
        switch (u8_type)
        {
            case BOOLEAN_TRUE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "true");
                break;
    
            case BOOLEAN_FALSE:
                frreport_body_l7_add_str(p_st_body_data, arr_key, "false");
                break;
    
            case BYTE:
                frthrift_tcompact_read_byte_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case I16:
                frthrift_tcompact_read_i16_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case I32:
                frthrift_tcompact_read_i32_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case I64:
                frthrift_tcompact_read_i64_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case DOUBLE:
                frthrift_tcompact_read_double_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case BINARY:
                frthrift_tcompact_read_binary_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case LIST:
                frthrift_tcompact_read_list_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case SET:
                frthrift_tcompact_read_set_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case MAP:
                frthrift_tcompact_read_map_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            case STRUCT:
                frthrift_tcompact_read_struct_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, arr_key);
                break;
    
            default:
                return FR_FAIL;
        }
        
    }
    
    return FR_SUCC;
    
}


/*!
 * \brief       thrift tcompact set 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_set_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    return frthrift_tcompact_read_list_begin(p_packet, p_st_body_data, p_st_compact, i_use_request, p_name);
}


/*!
 * \brief       thrift tcompact boolean 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_bool_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    uint8_t u8_type = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
        return FR_FAIL;
    
    if(u8_type == BOOLEAN_TRUE)
        frreport_body_l7_add_str(p_st_body_data, p_name, "true");
    else
        frreport_body_l7_add_str(p_st_body_data, p_name, "false");
    
    return FR_SUCC;
    
}


/*!
 * \brief       thrift tcompact byte 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_byte_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    uint8_t u8_type = 0;
    char arr_value[5];
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readByte(p_packet, &u8_type) == FR_FAIL)
        return FR_FAIL;
    
    snprintf(arr_value, sizeof(arr_value), "0x%02x", u8_type);
    
    frreport_body_l7_add_str(p_st_body_data, p_name, arr_value);
    
    return FR_SUCC;
    
}

/*!
 * \brief       thrift tcompact i16 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_i16_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    short s_tmp = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readI16(p_packet, &s_tmp) == FR_FAIL)
        return FR_FAIL;
    
    frreport_body_l7_add_int(p_st_body_data, p_name, s_tmp);
    
    return FR_SUCC;
    
}


/*!
 * \brief       thrift tcompact i32 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_i32_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    int i_tmp = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readI32(p_packet, &i_tmp) == FR_FAIL)
        return FR_FAIL;
    
    frreport_body_l7_add_int(p_st_body_data, p_name, i_tmp);
    
    return FR_SUCC;
    
}



/*!
 * \brief       thrift tcompact i64 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_i64_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    long l_tmp = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readI64(p_packet, &l_tmp) == FR_FAIL)
        return FR_FAIL;
    
    frreport_body_l7_add_long(p_st_body_data, p_name, l_tmp);
    
    return FR_SUCC;
    
}

/*!
 * \brief       thrift tcompact double 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_double_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    double db_tmp = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readDouble(p_packet, &db_tmp) == FR_FAIL)
        return FR_FAIL;
    
    frreport_body_l7_add_double(p_st_body_data, p_name, db_tmp);
    
    return FR_SUCC;
    
}

/*!
 * \brief       thrift tcompact string 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_string_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    char *p_tmp = NULL;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readString(p_packet, &p_tmp) == FR_FAIL)
        return FR_FAIL;
    
    frreport_body_l7_add_str(p_st_body_data, p_name, p_tmp);
    frfree(p_tmp);
    
    return FR_SUCC;
    
}


/*!
 * \brief       thrift tcompact string 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *              i_use_request       是否为请求数据
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_binary_begin(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact,int i_use_request, char *p_name)
{
    Frstr *p_st_str = NULL;
    char *p_str = NULL;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_name == NULL)
        return FR_FAIL;
    
    if(readBinary(p_packet, &p_st_str) == FR_FAIL)
        return FR_FAIL;
    
    if(fris_print_ascii(p_st_str->p_str, p_st_str->ui_len))
    {
        p_str = frstr_free2(&p_st_str);
        frreport_body_l7_add_str(p_st_body_data, p_name, p_str);
        frfree(p_str);
        return FR_SUCC;
    }
    frreport_body_l7_add_bin(p_st_body_data, p_name, p_st_str->p_str, p_st_str->ui_len);
    frstr_free(&p_st_str);
    
    return FR_SUCC;
    
}


/*!
 * \brief       thrift tcompact request 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_request(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact, char *p_prefix)
{
    int i_ret = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_prefix == NULL)
        return FR_FAIL;
    
    i_ret = frthrift_tcompact_read_message_begin(p_packet, p_st_body_data, p_st_compact, FR_YES, p_prefix);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    
    i_ret = frthrift_tcompact_read_field_begin(p_packet, p_st_body_data, p_st_compact, FR_YES, p_prefix);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    
    return FR_SUCC;
    
}

/*!
 * \brief       thrift tcompact response 解析
 *
 * \arg         p_packet            入力参数
 *              p_st_body_data      上报列表
 *              p_st_compact        tcompact 解析结构体
 *
 * \return      FR_SUCC
 *              FR_FAIL
 *
 */
int frthrift_tcompact_read_response(Frbyte_Packet *p_packet, Frreport_body_data *p_st_body_data
        , FRTcompact *p_st_compact, char *p_prefix)
{
    int i_ret = 0;
    
    if(p_packet == NULL || p_st_body_data == NULL || p_st_compact == NULL || p_prefix == NULL)
        return FR_FAIL;
    
    i_ret = frthrift_tcompact_read_message_begin(p_packet, p_st_body_data, p_st_compact, FR_NO, p_prefix);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    
    i_ret = frthrift_tcompact_read_field_begin(p_packet, p_st_body_data, p_st_compact, FR_NO, p_prefix);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    
    return FR_SUCC;
    
}
